[Do not merge] PEP 723 inline script env support design doc#1601
[Do not merge] PEP 723 inline script env support design doc#1601StellaHuang95 wants to merge 5 commits into
Conversation
|
@brettcannon Still can't assign you as a reviewer so tagging you here, any feedback is welcome, thank you! |
| - **Lazy on open + save** — parse only when the file enters an editor or | ||
| is saved. | ||
| - **Opt-in bulk command** — user runs `Python Envs: Set Up Environments for Inline Script Files` from the command palette to discover all of them, list every detected inline-script files in a multi-select quick-pick. | ||
|
|
There was a problem hiding this comment.
What about a third option (requires pylance's help), whenever the script header is detected by the Pylance parser.
This might happen if somebody opens a script that is referenced by another script with a header (imported by would be set in Pylance).
Example:
main_script.py (has the PEP 723 script)
tools.py (is referenced by PEP 723 script)
User edits tools.py
There was a problem hiding this comment.
I was mostly thinking to actually run or edit main_script.py, the user almost always opens it at some point. And once they open it once, the current mechanism captures it, so the inline env stays set up across sessions.
Are you thinking about the case where the user opens tools.py first, and is seeing squiggles on the imports? I agree that could be annoying. The tricky part for us is that the inline env is intentionally tied to the file with the PEP 723 header. For a file like tools.py to also pick up that env as its active one, we'd need to either register it as its own "project" pointing at someone else's env, or follow the import graph and pick a "best" inline env.
So my lean is probably not do this for v1 unless we can think of a good way to solve the problem above. Detect-on-open + persistence covers most real workflows, and the bulk command addresses the same underlying frustration in a simpler way:
A user exploring a new repo can set up every inline env in one shot without needing Pylance to drive discovery. Are you seeing lots of Pylance users complaining about that? If we hear that this still isn't enough I am happy to make some improvements.
There was a problem hiding this comment.
No sounds reasonable. I was just trying to think of other situations that could cause the env to be created. My idea was more about what background things could cause the env to automatically be created, and not necessarily about Pylance behaving correctly with respect to imports in the tools.py.
|
|
||
| **Decision.** | ||
|
|
||
| Reuse the existing venv persistence mechanism.Do not invent a new |
There was a problem hiding this comment.
This is going to require changes to Pylance outside of the work to support Python Environments sub environments because the environment in this case is tied to a file and not an entire folder.
Not sure if that will work correctly or not.
There was a problem hiding this comment.
yeah that's a good point, I think it requires changes on Pylance side to make it to work. I wonder how pylance work for notebook files, maybe we can do the same thing to look up env for files with inline script.
|
|
||
| ## 8. UX flows | ||
|
|
||
| **Question:** How does the user create envs — for a single script, and |
There was a problem hiding this comment.
Personally, I think the user should never have to create environments for the script. It should just happen automatically. What do they gain by having this command?
There was a problem hiding this comment.
Right now the envs extension runs on one shared extension host process, unlike pylance which has its own process and can do the heave-lifting in its own background thread without any architecture changes.
So for the bulk command I would rather keep it user triggered. A full workspace scan + per-file parse on a large repo is too much work and may block other. For single file case, I can probably add a codeLens that looks like this so that one click setup is obvious to user.
📦 Set up environment for this script
# /// script
# dependencies = ["requests"]
# ///
Context
PEP 723 defines inline script metadata — a
# /// script…# ///block at the top of a single-file Python script that declaresrequires-pythonanddependenciesinline, so the script is self-contained without apyproject.tomlorrequirements.txt. Tools likeuvandpipxalready honor it; users opening these scripts in VS Code today get no automatic environment support.This doc talks about how the extension should build, manage, and dispose of environments for those scripts.
What's in this doc
Eleven design questions, each with a proposed decision and the reasoning. The interesting / contentious ones:
<globalStorageUri>/script-envs-v1/<hash>/. Never inside the workspace.requires-python). The "no in-place sync" argument is the load-bearing one here.setEnvironment(scriptUri, env, /*persist*/ true)pipeline rather than inventing a new layer.setEnvironmentcall, with source pointers into Pylance and the Python extension to back the claim.Any feedback is welcome, thanks!